#include "HandController.h"
#include "HCINDI.h"

//#include "moc_HandController.cxx"

#include "ui_MountDisplay.h"
#include "ui_Pad.h"
#include "ui_HCSettings.h"
#include "ui_HandController.h"
#include "layout.h"

HandController::HandController(QWidget *parent)
:QMainWindow(parent), INDI::BaseClient()
{
  hApp->setHandController(this);
  
  settings = new QSettings();
  hApp->setSettings(settings);
  initSettings();
  
  // Haand Controller
  ui = new Ui::HandController();
  ui->setupUi(this);
  connect(ui->actionConnect_Mount, SIGNAL(triggered(bool)), this, SLOT(connectServer()));
  connect(this, SIGNAL(serverstatus(bool)), this, SLOT(changeServerStatus(bool)));
  connect(this, SIGNAL(mountconnected(INDI::BaseDevice*)), this, SLOT(changeMountStatus(INDI::BaseDevice*)));
  initInfo();
  
  // Mount status  
  mountdisplay=new MountDisplay();
  hApp->setMountDisplay(mountdisplay);
  mountdisplay->setupUi(ui->framemountDisplay);
  connect(this, SIGNAL(lstchanged(double)), mountdisplay, SLOT(changeLST(double)));
  connect(this, SIGNAL(equatorialchanged(double,double)), mountdisplay, SLOT(changeEquatorialCoords(double,double)));
  connect(this, SIGNAL(horizontalchanged(double,double)), mountdisplay, SLOT(changeHorizontalCoords(double,double)));

  //Pad
  pad = new Pad(this);
  hApp->setPad(pad);
  pad->setupUi(ui->framemountPad);
  connect(this, SIGNAL(mountconnected(INDI::BaseDevice*)), pad, SLOT(setTelescope(INDI::BaseDevice *)));
  connect(this, SIGNAL(speedindexchanged(int)), pad, SLOT(setSpeedIndex(int)));
  connect(this, SIGNAL(newgoto(double,double)), pad, SLOT(addGoto(double,double)));  
  connect(pad, SIGNAL(lastgotosynced(double,double)), this, SLOT(marklastGotoasSynced(double,double)));
  
  //Settings
  hcsettings = new HCSettings();
  hApp->setHCSettings(hcsettings);
  hcsettings->setupUi();
  connect(ui->actionSettings, SIGNAL(triggered(bool)), hcsettings, SLOT(exec(bool)));
  
  isGoto=false;
}

void HandController::initSettings()
{
  server=settings->value("indi/server", "localhost").toString();
  port=settings->value("indi/port", "7624").toString();
  mountname=settings->value("indi/mountname", "EQMod Mount").toString();
  
  settings->beginGroup("joypad");
  settings->beginGroup("layouts");
  settings->beginGroup("INDI Default");
  settings->beginGroup("joystick 1");
  settings->beginWriteArray("buttons");
  settings->setArrayIndex(0);
  settings->setValue("value", "button 1: indi NORTH");
  settings->setArrayIndex(1);
  settings->setValue("value", "button 2: indi EAST");
  settings->setArrayIndex(2);
  settings->setValue("value", "button 3: indi SOUTH");
  settings->setArrayIndex(3);
  settings->setValue("value", "button 4: indi WEST");
  settings->setArrayIndex(4);
  settings->setValue("value", "button 6: indi SPEED+");
  settings->setArrayIndex(5);
  settings->setValue("value", "button 8: indi SPEED-");
  settings->setArrayIndex(6);
  settings->setValue("value", "button 10: indi SYNC");  
  settings->setArrayIndex(7);
  settings->setValue("value", "button 12: indi ABORT");  
  settings->endArray();
  settings->endGroup();
  settings->endGroup();
  settings->endGroup();  
  settings->endGroup();
  
}

void HandController::initInfo()
{
  connect(this, SIGNAL(observerchanged(double,double)), SLOT(changeObserver(double,double)));
  connect(this, SIGNAL(utcchanged(QString)), SLOT(changeUTC(QString)));
  ui->comboBoxinfo->addItems(QStringList()<<"Observer"<<"Time"<<"Gotos");
  connect(ui->comboBoxinfo, SIGNAL(activated(int)), ui->stackedWidgetInfo, SLOT(setCurrentIndex(int)));
  
  ui->tableWidgetgotos->setColumnCount(2);
  ui->tableWidgetgotos->setHorizontalHeaderLabels(QStringList()<<"RA" <<"DEC");
  ui->tableWidgetgotos->verticalHeader()->hide();
  ui->tableWidgetgotos->setSelectionBehavior(QAbstractItemView::SelectRows);
  ui->tableWidgetgotos->setSelectionMode(QAbstractItemView::SingleSelection);
  ui->tableWidgetgotos->setDragDropMode(QAbstractItemView::NoDragDrop);
  ui->tableWidgetgotos->setEditTriggers(QAbstractItemView::NoEditTriggers);  
  //ui->tableWidgetgotos->resizeColumnsToContents();
  //ui->tableWidgetgotos->resizeRowsToContents();
  connect(this, SIGNAL(newgoto(double,double)), this, SLOT(addGoto(double,double)));

}


void HandController::closeEvent(QCloseEvent* event)
{
  hcsettings->getLayoutManager()->saveDefault();
  event->accept();
}


void HandController::newDevice(INDI::BaseDevice *dp)
{
  //std::printf("new device %s\n", dp->getDeviceName());
  //IDLog("new device %s\n", dp->getDeviceName());
  if (QString(dp->getDeviceName()) == mountname) {
   mountdevice = dp;


  }
  //ui->comboBoxDevice->addItem(dp->getDeviceName(), QVariant::fromValue<INDI::BaseDevice *>(dp));
}

void HandController::newProperty(INDI::Property* property)
{
 
  //IDLog("new property %s %d\n", property->getName(), property->getType());
  if (not mountdevice) return;
  if (not strcmp(property->getDeviceName(), mountdevice->getDeviceName())) {
    if (not strcmp(property->getName(), "CONNECTION"))
    {   
      mountwasconnected=false;
      if (mountdevice->isConnected()) mountwasconnected=true; 
      INDI::BaseClient::connectDevice(mountdevice->getDeviceName());
      emit mountconnected(mountdevice);
      return;
    }
    if (not strcmp(property->getName(), "GEOGRAPHIC_COORD")) {
      INumberVectorProperty *nvp=property->getNumber();
      obs_lat=IUFindNumber(nvp,"LAT")->value;
      obs_lon=IUFindNumber(nvp, "LONG")->value;
      emit observerchanged(obs_lon, obs_lat);
    }
  }
  //if (not indidevice) return;

}

void HandController::removeProperty(INDI::Property *property) 
{
  
}

void HandController::newBLOB(IBLOB *bp)
{

}

void HandController::newSwitch(ISwitchVectorProperty *svp) 
{
  if (not mountdevice) return;
  if (not strcmp(svp->device, mountdevice->getDeviceName())) {
    if (not strcmp(svp->name, "SLEWMODE")) {
     int index = IUFindOnSwitchIndex(svp);
     emit speedindexchanged(index);
    }
    if (not strcmp(svp->name, "ON_COORD_SET")) {
     ISwitch *switchoncoord = IUFindOnSwitch(svp);
     if ((switchoncoord) && ((!strcmp(switchoncoord->name, "SLEW")) || (!strcmp(switchoncoord->name, "TRACK")))) {
      isGoto = true; 
     }
     else {
      isGoto = false; 
     }
    }    
    
  }
}

void HandController::newNumber(INumberVectorProperty *nvp)
{
  
  //if (not mountdevice) return;
  

  if (not mountdevice) return;
  if (not strcmp(nvp->device, mountdevice->getDeviceName())) {
    if (not strcmp(nvp->name, "GEOGRAPHIC_COORD")) {
      obs_lat=IUFindNumber(nvp,"LAT")->value;
      obs_lon=IUFindNumber(nvp, "LONG")->value;
      emit observerchanged(obs_lon, obs_lat);
    }  
    if (not strcmp(nvp->name, "TIME_LST")) {
      INumber *ilst;
      ilst=IUFindNumber(nvp,"LST");
      if (ilst)
	obs_lst=ilst->value;
      emit lstchanged(obs_lst);
    }

    if (not strcmp(nvp->name, "EQUATORIAL_EOD_COORD")) {
      INumber *inum;
      inum=IUFindNumber(nvp,"RA");
      if (inum)
	currentRA=inum->value;
      inum=IUFindNumber(nvp,"DEC");
      if (inum)
	currentDEC=inum->value;
      if (!inGoto) inGoto = (nvp->s == IPS_BUSY); 
      if (isGoto && inGoto && (nvp->s == IPS_OK)) {
        emit newgoto(currentRA, currentDEC);
	//printf("Goto RA=%g DEC=%g\n", currentRA, currentDEC);
	inGoto = false;
      }
      emit equatorialchanged(currentRA, currentDEC);
    }    
    if (not strcmp(nvp->name, "HORIZONTAL_COORD")) {
      INumber *inum;
      inum=IUFindNumber(nvp,"ALT");
      if (inum)
	currentAlt=inum->value;
      inum=IUFindNumber(nvp,"AZ");
      if (inum)
	currentAz=inum->value;
      emit horizontalchanged(currentAlt, currentAz);
    }    
    
  }
  
}

void HandController::newMessage(INDI::BaseDevice *dp, int messageID)
{
  
}

void HandController::newText(ITextVectorProperty *tvp)
{
  if (not mountdevice) return;
    if (not strcmp(tvp->device, mountdevice->getDeviceName())) {
      if (not strcmp(tvp->name, "TIME_UTC")) {
      IText *iutc;
      iutc=IUFindText(tvp,"UTC");
      if (iutc)
	obs_utc=QString(iutc->text);
      emit utcchanged(obs_utc);
    }
  }
}

void HandController::newLight(ILightVectorProperty *lvp)
{
  
}

bool HandController::connectServer()
{
  //std::printf("Connecting...");
  //uiservers->show();
  setServer(server.toAscii(), port.toUInt());
  watchDevice(mountname.toAscii());
  ui->statusbar->showMessage("Connecting...");	
  if (not INDI::BaseClient::connectServer()) {
    ui->statusbar->showMessage("Connection failed");
  }
}

bool HandController::disconnectServer()
{
  //std::printf("Connecting...");
  ui->statusbar->showMessage("Disconnecting...");
  INDI::BaseClient::disconnectServer();
}

void HandController::changeServerStatus(bool status)
{
  if (status) {
    ui->actionConnect_Mount->setText("Disconnect");
    QObject::disconnect(ui->actionConnect_Mount, SIGNAL(triggered()), this, SLOT(connectServer()));
    QObject::connect(ui->actionConnect_Mount, SIGNAL(triggered()), this, SLOT(disconnectServer())); 
    ui->statusbar->showMessage("Connected.");
  } else {
    ui->actionConnect_Mount->setText("Connect");
    QObject::disconnect(ui->actionConnect_Mount, SIGNAL(triggered()), this, SLOT(disconnectServer()));
    QObject::connect(ui->actionConnect_Mount, SIGNAL(triggered()), this, SLOT(connectServer())); 
    ui->statusbar->showMessage("Disconnected.");
  }
}

void HandController::changeMountStatus(INDI::BaseDevice *d)
{
   ui->statusbar->showMessage("Mount Connected");
}

void HandController::changeObserver(double lng, double lat)
{
  char latsexa[11];
  char lonsexa[11];
  fs_sexa(latsexa, lat, 2, 3600);
  ui->labellat->setText(QString("Lat: ")+QString(latsexa));
  fs_sexa(lonsexa, lng, 3, 3600);
  ui->labellon->setText(QString("Lon: ")+QString(lonsexa));
  statusBar()->showMessage(QString("Observer - Lat: ")+QString(latsexa)+QString("Lon: ")+QString(lonsexa));
}

void HandController::changeUTC(QString utc)
{
  ui->labelUTC->setText("UTC:"+utc);
}

void HandController::addGoto(double ra, double dec)
{
  coord_t s;
  s.ra = ra; s.dec = dec;
  gotos.insert(0, s);
  char coordsexa[11];
  fs_sexa(coordsexa, ra, 3, 3600);
  ui->tableWidgetgotos->insertRow(0);
  ui->tableWidgetgotos->setItem(0, 0, new QTableWidgetItem(QString(coordsexa)));
  fs_sexa(coordsexa, dec, 3, 3600);	
  ui->tableWidgetgotos->setItem(0, 1, new QTableWidgetItem(QString(coordsexa)));
  ui->tableWidgetgotos->resizeColumnsToContents();
  ui->tableWidgetgotos->resizeRowsToContents();
}

void HandController::marklastGotoasSynced(double tra, double tdec)
{
  ui->tableWidgetgotos->item(0,0)->setBackground(QBrush(QColor("#CCFFFF")));
  ui->tableWidgetgotos->item(0,1)->setBackground(QBrush(QColor("#CCFFFF")));
}


void HandController::serverConnected()
{
  emit serverstatus(true);
  emit serverconnected();
}

void HandController::serverDisconnected(int exit_code)
{
  emit serverstatus(false);
  emit serverdisconnected(exit_code);  
}  

// Getters/Setters
QString HandController::getServerName()
{
  return server;
}
QString HandController::getPortString()
{
  return port;
}
QString HandController::getMountName()
{
  return mountname;
}

void HandController::setServerName(QString s)
{
  server = s;
}

void HandController::setPortString(QString s)
{
  port = s;
}

void HandController::setMountName(QString s)
{
  mountname = s;
}


